<?php
namespace cubox;

class Route{
    
    public static function parse($urlPath){
        $pathList = explode('/', $urlPath);
        
        if (isset($pathList[1]) && $pathList[1]!='' && $pathList[1]=='app'){
            
            $currentApp = '';
            $currentController = 'index';
            $currentAction = 'index';
            $_gets = [];
            if ($pathList[1]=='app'){
                if (isset($pathList[2]) && $pathList[2]!='')   $currentApp = $pathList[2];
                if (isset($pathList[3]) && $pathList[3]!='')   $currentController = $pathList[3];
                if (isset($pathList[4]) && $pathList[4]!='')   $currentAction = $pathList[4];
            }
    
            if (count($pathList)>4){
                 
                 for($i=5;$i<count($pathList);$i=$i+2){
                     if (isset($pathList[$i]) && $pathList[$i]!='' && isset($pathList[$i+1]) && $pathList[$i+1]!=''){
                         $_gets[$pathList[$i]] = $pathList[$i+1];
                     }
                 }
             }
    
             //别名
             $alias = Cubox::config('alias')->toArray();
             
             if ($currentApp==''){
                 throw new \Exception('No app.');
             }
    
             if (isset($alias[$currentApp]) && $alias[$currentApp]!=''){
                 throw new \Exception('APP is not exists.');    
             }
    
             if (in_array($currentApp,$alias)){
                 $currentApp = array_search($currentApp,$alias);
             }

             return [
                'app' => $currentApp,
                'controller' => $currentController,
                'action' => $currentAction,
                'gets' => $_gets,
            ];

        }else{
            
            return self::custom($urlPath);  
        }
    }
     /**
     * 解析自定义路由
     * @param string $path 路由地址
     * @return array
     */
    public static function custom(string $path,string $app='',$param = null):array{

        $routeData = self::getRouteData($app,$param);
      
        $fixed  = $routeData['fixed'];
        $unfixed  = $routeData['unfixed'];
        $re = null;//
        if (isset($fixed[$path])){
            $re  =  $fixed[$path];
        }else{

            $pathArr = explode('/',$path);
            $length = count($pathArr);

            if (isset($unfixed[$length])){
                foreach($unfixed[$length] as $val){
                    if (self::match($pathArr,$val['path'])){

                        if (!isset($val['gets'])) $val['gets'] = []; 

                        foreach($val['path'] as $k=>$v){
                            if (substr($v,0,1)==':'){
                                $val['gets'][substr($v,1)] = $pathArr[$k];
                            }
                        }

                        $re = $val;
                        break;
                    }
                }
            }
        }

        if (is_null($re)){
            throw new \Exception('Route not exists:'.$path);
        }else{
            return $re;
        }
    }

    /**
     * 获取路由数据
     */

     private static function getRouteData(string $app='',$param = null):array{
        $cache = Cubox::cache();
        $cacheName = $app==''?'__cubox_route':'__cubox_'.$app.'_route';
        if ($app!='') $param['app'] =  true;
        
        if ($cache->exists($cacheName)){
            return $cache->get($cacheName)??['fixed'=>[],'unfixed'=>[]];
        }else{
            $plugs = Cubox::plug('Route');
            
            $fixed  = [];
            $unfixed  = [];
             
            foreach($plugs as $name=>$plug){

                if ($app=='' || $name==$app){

                    $list = $plug->getData($param);

                    if (is_array($list)){
                        foreach($list  as $key => $val){
                            if (strpos($key,':')===false){
                                $fixed[$key]=$val;
                            }else{
                                $path =  explode('/',$key);
                                $length = count($path);
                                $val['path'] = $path;
                                $unfixed[$length][$key]=$val;
                            }
                        }
                    }
                }
                
            }

            $re = ['fixed'=>$fixed,'unfixed'=>$unfixed];
            $cache->set($cacheName,json_encode($re));
            return $re;
        }

        return [];
    }
    
    public static function clearCache($app){
        $cache = Cubox::cache();
        $cacheName = $app==''?'__cubox_route':'__cubox_route'.$app.'_route';
        $cache->delete($cacheName);
    }

    private static function match($pathArr,$routeArr){
        foreach($routeArr as $k=>$v){
            if (substr($v,0,1)!=':'){
                if ($v!=$pathArr[$k]) return false;
            }else{
                //防止出现根目录变量
                if ($k>1) return true;
            }
        }
    }
}